package com.xored.searchwt;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.StatusLineLayoutData;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IStatusField;
import org.eclipse.ui.texteditor.IStatusFieldExtension;

/**
 * @author Yuri Strot
 *
 */
public class SearchStatusLine extends ContributionItem 
		implements IStatusField, IStatusFieldExtension, ISearchView {
	
	private static SearchStatusLine statusLineSearch;
	
	public static SearchStatusLine getInstance() {
		if (statusLineSearch == null) {
			statusLineSearch = new SearchStatusLine();
			if (SearchAgent.isCanBeActivated(statusLineSearch))
				statusLineSearch.init();
			else {
				statusLineSearch = null;
			}
		}
		return statusLineSearch;
	}
	
	private SearchControl control;
	
	private SearchStatusLine() {
	}
	
	protected void init() {
		control = new SearchControl();
		control.initAgent(this);
	}
	
	public void activate() {
		if (control != null) {
			control.setFocus();
		}
	}
	
	/*
	 * @see IContributionItem#fill(Composite)
	 */
	public void fill(Composite parent) {
		Label sep = new Label(parent, SWT.SEPARATOR);
		control.create(parent);

		StatusLineLayoutData data= new StatusLineLayoutData();
		data.heightHint= getHeightHint(parent);
		sep.setLayoutData(data);
	}
	
	public Shell getShell() {
		IWorkbenchWindow window = getWindow();
		if (window != null)
			return window.getShell();
		return null;
	}
	
	public IWorkbenchWindow getWindow() {
		return PlatformUI.getWorkbench().getActiveWorkbenchWindow();
	}
	
	public boolean ignore(IWorkbenchPart part) {
		return false;
	}
	
	public void backFocus() {
		if (managerList.size() > 0) {
			Iterator it = managerList.iterator();
			while (it.hasNext()) {
				IStatusLineManager manager =
					(IStatusLineManager) it.next();
				manager.remove(this);
				manager.update(false);
			}
		}
		control.dispose();
		control = null;
		statusLineSearch = null;
	}
	
	public void update(IWorkbenchPart part, boolean highlight, String text) {
		IStatusLineManager manager = null;
		if (part instanceof IEditorPart) {
			IEditorPart editor = (IEditorPart)part;
			manager = editor.getEditorSite().getActionBars().getStatusLineManager();
		}
		else if (part instanceof IViewPart) {
			IViewPart view = (IViewPart)part;
			manager = view.getViewSite().getActionBars().getStatusLineManager();
		}
		if (manager != null) {
			manager.remove(this);
			manager.add(this);
			manager.update(true);
			managerList.add(manager);
			control.update(part, highlight, text);
		}
	}
	
	public void updateHighlightCount(int count) {
		control.updateHighlightCount(count);
	}
	                                             
	
	public void initTextLayout(Composite parent, Control text) {
		StatusLineLayoutData data= new StatusLineLayoutData();
		data.widthHint= getWidthHint(parent);
		text.setLayoutData(data);
	}
	
	public void initLabelLayout(Composite parent, Control label) {
		StatusLineLayoutData data= new StatusLineLayoutData();
		data.heightHint = getHeightHint(parent);
		label.setLayoutData(data);
	}

	public void setImage(Image image) {
	}

	public void setText(String text) {
	}

	public void setErrorImage(Image image) {
		setImage(image);
	}

	public void setErrorText(String text) {
		setText(text);
	}

	public void setToolTipText(String string) {
		setText(string);
	}

	/**
	 * Left and right margin used in CLabel.
	 * @since 2.1
	 */
	private static final int INDENT= 3;

	/**
	 * Returns the width hint for this label.
	 *
	 * @param control the root control of this label
	 * @return the width hint for this label
	 * @since 2.1
	 */
	int getWidthHint(Composite control) {
		if (fFixedWidth < 0) {
			GC gc= new GC(control);
			gc.setFont(control.getFont());
			fFixedWidth= gc.getFontMetrics().getAverageCharWidth() * DEFAULT_WIDTH_IN_CHARS;
			fFixedWidth += INDENT * 2;
			gc.dispose();
		}
		return fFixedWidth;
	}

	/**
	 * Returns the height hint for this label.
	 *
	 * @param control the root control of this label
	 * @return the height hint for this label
	 * @since 3.0
	 */
	int getHeightHint(Composite control) {
		if (fFixedHeight < 0) {
			GC gc= new GC(control);
			gc.setFont(control.getFont());
			fFixedHeight= gc.getFontMetrics().getHeight();
			gc.dispose();
		}
		return fFixedHeight;
	}
	
	int DEFAULT_WIDTH_IN_CHARS = 20;
	private int fFixedWidth= -1;
	private int fFixedHeight= -1;
	private List managerList = new ArrayList();

}
